`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2021/08/03 20:20:35
// Design Name: 
// Module Name: MultiBankBramTest
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module MultiBankBramTest;
parameter DATA_WIDTH = 32;
parameter ADDR_WIDTH = 32;
parameter DEPTH = 1024;
parameter BANK = 4;
logic clk;
logic rst;
logic [ADDR_WIDTH-1:0] rd_addr [0:BANK-1];
logic [DATA_WIDTH-1:0] rd_data [0:BANK-1];
logic [ADDR_WIDTH-1:0] wr_addr [0:BANK-1];
logic [DATA_WIDTH-1:0] wr_data [0:BANK-1];
logic we [0:BANK-1];
logic [DATA_WIDTH-1:0] mem [0:DEPTH*BANK-1];
logic start_write;
logic start_write_ff;
logic write_done;
logic [31:0] write_cnt;
logic start_read;
logic read_done;
logic writing;
logic writing_ff;
//
always_ff@(posedge clk)
    writing_ff<=writing;
//clk
initial begin
    clk=0;
    forever 
        #5 clk=~clk;
end
//rst
initial begin
    rst=1;
    #20
    rst=0;
end
//start_write
initial begin
    start_write=0;
    #100
    start_write=1;
    #10
    start_write=0;
end
//mem
initial begin
    for(int i=0;i<BANK*10;i++)
        mem[i]=i;
end
//writing
always_ff@(posedge clk,posedge rst)
if(rst)
    writing<=0;
else if(start_write)
    writing<=1;
else if(write_done)
    writing<=0;
//we
always_ff@(posedge clk)
if(writing)
begin
    for(int i=0;i<BANK;i++)
        we[i]<=1'b0;
    if(write_cnt<10-1)
        we[0]<=1'b1;
    else if(write_cnt<20-1)
        we[1]<=1'b1;
    else if(write_cnt<30-1)
        we[2]<=1'b1;
    else if(write_cnt<40-1)
        we[3]<=1'b1;    
end
//write_addr
always_comb
if(we[0])               //写0-9
begin
    wr_addr[0]=write_cnt;
    wr_addr[1]=0;
    wr_addr[2]=0;
    wr_addr[3]=0;
end
else if(we[1])
begin
    wr_addr[0]=0;
    wr_addr[1]=write_cnt-10;
    wr_addr[2]=0;
    wr_addr[3]=0;
end
else if(we[2])
begin
    wr_addr[0]=0;
    wr_addr[1]=0;
    wr_addr[2]=write_cnt-20;
    wr_addr[3]=0;
end
else if(we[3])
begin
    wr_addr[0]=0;
    wr_addr[1]=0;
    wr_addr[2]=0;
    wr_addr[3]=write_cnt-30;
end
else
begin
    wr_addr[0]=0;
    wr_addr[1]=0;
    wr_addr[2]=0;
    wr_addr[3]=0;
end
//write_data
always_comb
if(we[0])
begin
    wr_data[0]=mem[write_cnt];
    wr_data[1]=0;
    wr_data[2]=0;
    wr_data[3]=0;
end
else if(we[1])
begin
    wr_data[0]=0;
    wr_data[1]=mem[write_cnt];
    wr_data[2]=0;
    wr_data[3]=0;
end
else if(we[2])
begin
    wr_data[0]=0;
    wr_data[1]=0;
    wr_data[2]=mem[write_cnt];
    wr_data[3]=0;
end
else if(we[3])
begin
    wr_data[0]=0;
    wr_data[1]=0;
    wr_data[2]=0;
    wr_data[3]=mem[write_cnt];
end
//write_cnt
always_ff@(posedge clk,posedge rst)
if(rst)
    write_cnt<=0;
else if(start_write)
    write_cnt<=0;
else if(writing_ff)
    write_cnt<=write_cnt+1;
//write_done
always_ff@(posedge clk,posedge rst)
if(rst)
    write_done<=0;
else if(write_cnt==4*10-1)
    write_done<=1;
else 
    write_done<=0;
//start_read
always_ff@(posedge clk,posedge rst)
if(rst)
    start_read<=0;
else if(write_done)
    start_read<=1;
else
    start_read<=0;
//rd_addr
always_ff@(posedge clk)
if(start_read)
for(int i=0;i<BANK;i++)
    rd_addr[i]<=0;
else
for(int i=0;i<BANK;i++)
    rd_addr[i]<=rd_addr[i]+1;
//
assign read_done=(rd_addr[0]==10-1)?1'b1:1'b0;

//rd_data

//instance
MultiBankBram
#(.BANK(4),
  .DATA_WIDTH(32),
  .ADDR_WIDTH(32),
  .DEPTH(1024))
U(
.clk(clk),
.rst(rst),
//write
.we(we),
.wr_addr(wr_addr),
.wr_data(wr_data),
//read
.rd_addr(rd_addr),
.rd_data(rd_data)
    );
endmodule
